package com.demo.project_template.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.demo.project_template.entity.Product;
import com.demo.project_template.entity.ProductSpec;
import com.demo.project_template.entity.ShoppingCart;
import com.demo.project_template.entity.User;
import com.demo.project_template.exception.ErrorCodeException;
import com.demo.project_template.exception.ErrorCodeExceptionEnum;
import com.demo.project_template.mapper.ProductMapper;
import com.demo.project_template.mapper.ProductSpecMapper;
import com.demo.project_template.mapper.UserMapper;
import com.demo.project_template.service.ShoppingCartService;
import com.demo.project_template.util.CheckEmptyUtil;
import com.demo.project_template.util.RedisUtil;
import com.demo.project_template.vo.request.shoppingcart.*;
import com.demo.project_template.vo.response.R;
import lombok.extern.log4j.Log4j2;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.demo.project_template.constant.CommonConstants.CART_REDIS_KEY_TEMPLATE;


@Log4j2
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class ShoppingCartImpl implements ShoppingCartService {
    @Resource
    private ProductMapper productMapper;
    @Resource
    private ProductSpecMapper productSpecMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserMapper userMapper;

    /**
     * 添加商品购物车
     */
    @Override
    public synchronized void addShoppingCart(CartAddVO cartAddVo) {
         /**
          * 查询商品是否存在
         * 写入到redis(redis中有数量加一，redis中无添加数据)
         */
        ProductSpec productSpec = productSpecMapper.selectOne(new LambdaQueryWrapper<ProductSpec>().eq(ProductSpec::getProductSpec,cartAddVo.getProductSpec()));
        if (CheckEmptyUtil.isEmpty(productSpec)) {
            throw new ErrorCodeException(500,"规格不存在");
        }
        if (productSpec.getStock()<=0){
            throw new ErrorCodeException(500,"商品库存不足");
        }
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, cartAddVo.getUserId());
        ShoppingCart cart;
        String value = redisUtil.hget(redisKey, cartAddVo.getProductSpec());
        log.info("用户添加的商品在redis拥有详情：[{}]", value);
        if (CheckEmptyUtil.isEmpty(value)) {
            //没有该商品, 新增
            cart = new ShoppingCart(productSpec.getProductId(),productSpec.getProductSpecsId(), 1, cartAddVo.getSelected());
        } else {
            //已经有了，数量+1
            cart = com.alibaba.fastjson2.JSON.parseObject(value, ShoppingCart.class);
            cart.setQuantity(cart.getQuantity() + 1);
        }
        redisUtil.hset(redisKey, productSpec.getProductSpecsId().toString(), JSON.toJSONString(cart));
    }

    /**
     * 查询用户购物车中的商品
     *
     * @param userId 用户id
     * @return SelectShoppingCartListVO
     */
    @Override
    public SelectShoppingCartListVO selectShoppingCartList(Long userId) {
        boolean selectAll = true;
        int cartTotalQuantity = 0;
        BigDecimal cartTotalPrice = BigDecimal.ZERO;
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        /**
         *  在redis中获取用户购物车信息
         *  构建vo参数
         */
        log.info("redisKey：[{}]", redisKey);
        Map<Object, Object> userCartMap = redisUtil.hmget(redisKey);
        if (CheckEmptyUtil.isEmpty(userCartMap)) {
            throw new ErrorCodeException(50052,"购物车空荡荡的");
        }
        log.info("用户购物车：[{}]", userCartMap.toString());
        //获取用户购物车的productId
        ArrayList<ProductSpec> userProductSpecs = new ArrayList();
        userCartMap.forEach((key,value)->{
            ProductSpec productSpec = productSpecMapper.selectById(Integer.valueOf(key.toString()));
            if (!CheckEmptyUtil.isEmpty(productSpec)){
                userProductSpecs.add(productSpec);
            }else {
                redisUtil.hdel(redisKey, (String) key);
            }
        });
        //构建vo
        List<CartProductVO> cartProductVoList = new ArrayList<>();
        for (ProductSpec productSpec : userProductSpecs) {
            ShoppingCart shoppingCart = JSON.parseObject(userCartMap.get(productSpec.getProductSpecsId()).toString(), ShoppingCart.class);
            Product petProduct = productMapper.selectById(productSpec.getProductId());
            CartProductVO cartProductVo = new CartProductVO();
            BeanUtils.copyProperties(productSpec, cartProductVo);
            BeanUtils.copyProperties(petProduct,cartProductVo);
            cartProductVo.setProductSelected(shoppingCart.getProductSelected());
            cartProductVoList.add(cartProductVo);
            if (!shoppingCart.getProductSelected()) {
                selectAll = false;
            }
            if (shoppingCart.getProductSelected()) {
                cartTotalPrice = cartTotalPrice.add(cartProductVo.getProductPrice());
            }
            cartTotalQuantity += 1;
        }
        SelectShoppingCartListVO selectShoppingCartListVo = new SelectShoppingCartListVO();
        //有一个没有选中，就不叫全选
        selectShoppingCartListVo.setSelectedAll(selectAll);
        selectShoppingCartListVo.setCartTotalQuantity(cartTotalQuantity);
        selectShoppingCartListVo.setCartTotalPrice(cartTotalPrice);
        selectShoppingCartListVo.setCartProductVoList(cartProductVoList);
        return selectShoppingCartListVo;
    }

    /**
     * 购物车全选
     */

    @Override
    public SelectShoppingCartListVO selectAllCart(Long userId) {
        /**
         * 获取用户的购物车
         * 遍历将状态转化为选中状态
         */
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        List<ShoppingCart> shoppingCarts = listForCart(userId);
        shoppingCarts.forEach(item -> {
            if (!item.getProductSelected()) {
                item.setProductSelected(true);
                redisUtil.hset(redisKey, (item.getProductSpecId().toString()), JSON.toJSONString(item));
            }
        });
        return selectShoppingCartList(userId);
    }

    /**
     * 购物车全不选
     */

    @Override
    public SelectShoppingCartListVO unSelectAllCart(Long userId) {
        /**
         * 获取用户的购物车
         * 遍历将状态转化为选中状态
         */
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        List<ShoppingCart> shoppingCarts = listForCart(userId);
        shoppingCarts.forEach(item -> {
            if (item.getProductSelected()) {
                item.setProductSelected(false);
                redisUtil.hset(redisKey, (item.getProductSpecId().toString()), JSON.toJSONString(item));
            }
        });
        return selectShoppingCartList(userId);
    }

    /**
     * 修改购物车
     */
    @Override
    public List<ShoppingCart> updateShoppingCart(CartUpdateVO cartUpdateVo) {
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, cartUpdateVo.getUserId());
        String value = redisUtil.hget(redisKey, (cartUpdateVo.getProductSpecId().toString()));
        if (CheckEmptyUtil.isEmpty(value)) {
            redisUtil.hdel(redisKey,cartUpdateVo.getProductSpecId().toString());
            //没有该商品, 报错
            throw new ErrorCodeException(500,"商品已下架");
        }
        if (cartUpdateVo.getQuantity()<=0){
            redisUtil.hdel(redisKey,cartUpdateVo.getProductSpecId().toString());
            return listForCart(cartUpdateVo.getUserId());
        }
        //已经有了，修改内容
        ShoppingCart shoppingCart = JSON.parseObject(value, ShoppingCart.class);
        if (cartUpdateVo.getQuantity() != null && cartUpdateVo.getQuantity() >= 0) {
            shoppingCart.setQuantity(cartUpdateVo.getQuantity());
        }
        if (cartUpdateVo.getSelected() != null) {
            shoppingCart.setProductSelected(cartUpdateVo.getSelected());
        }
        redisUtil.hset(redisKey, (cartUpdateVo.getProductSpecId().toString()), JSON.toJSONString(shoppingCart));
        return listForCart(cartUpdateVo.getUserId());
    }

    /**
     * 删除购物车（批量）
     */
    @Override
    public List<ShoppingCart> deleteShoppingCart(DeleteShoppingCartVO deleteShoppingCartList) {
        if (CheckEmptyUtil.isEmpty(deleteShoppingCartList)) {
            throw new ErrorCodeException(ErrorCodeExceptionEnum.SYSTEM_ERROR);
        }
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, deleteShoppingCartList.getUserId());
        deleteShoppingCartList.getDeleteShoppingProjects().forEach(item -> {
            String value = redisUtil.hget(redisKey, (item.getProductSpecId().toString()));
            if (!CheckEmptyUtil.isEmpty(value)) {
                //没有该商品, 报错
                redisUtil.hdel(redisKey, item.getProductSpecId().toString());
            }
        });
        return listForCart(deleteShoppingCartList.getUserId());
    }

    /**
     * 查询用户购物车缓存
     */

    @Override
    public List<ShoppingCart> listForCart(Long userId) {
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        Map<Object, Object> entries = redisUtil.hmget(redisKey);
        List<ShoppingCart> cartList = new ArrayList<>();
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            cartList.add(JSON.parseObject((String) entry.getValue(), ShoppingCart.class));
        }
        return cartList;
    }

    /**
     * 查询用户购物车中选中的商品
     */

    @Override
    public List<ShoppingCart> listForCartChecked(Long userId) {
        List<ShoppingCart> cartList = getShoppingCarts(userId);
        return cartList;
    }

    /**
     * 查询用户购物车中选中的商品
     */

    @Override
    public List<ListForCartCheckedVO> listForCartCheckedProduct(Long userId) {
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        List<ShoppingCart> cartList = getShoppingCarts(userId);
        List<ListForCartCheckedVO> listForCartCheckedList = new ArrayList<>();
        if (!CheckEmptyUtil.isEmpty(cartList)) {
            cartList.forEach(item -> {
                ProductSpec productSpec = productSpecMapper.selectById(item.getProductSpecId());
                Product petProduct = productMapper.selectById(productSpec.getProductId());
                if (!CheckEmptyUtil.isEmpty(petProduct) && !CheckEmptyUtil.isEmpty(productSpec)){
                    ListForCartCheckedVO listForCartChecked = new ListForCartCheckedVO();
                    BeanUtils.copyProperties(petProduct, listForCartChecked);
                    BeanUtils.copyProperties(productSpec, listForCartChecked);
                    listForCartCheckedList.add(listForCartChecked);
                }else {
                    redisUtil.hdel(redisKey, item.getProductSpecId().toString());
                }
            });
        }
        return listForCartCheckedList;
    }

    @NotNull
    private List<ShoppingCart> getShoppingCarts(Long userId) {
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        Map<Object, Object> entries = redisUtil.hmget(redisKey);
        List<ShoppingCart> cartList = new ArrayList<>();
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            ShoppingCart shoppingCart = JSON.parseObject((String) entry.getValue(), ShoppingCart.class);
            if (shoppingCart.getProductSelected()) {
                cartList.add(shoppingCart);
            }
        }
        return cartList;
    }

    /**
     * 删除用户购物车中选中的商品
     */

    @Override
    public void deleteCartChecked(Long userId) {
        List<ShoppingCart> shoppingCarts = this.listForCartChecked(userId);
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
        shoppingCarts.forEach(item -> {
            redisUtil.hdel(redisKey, item.getProductSpecId().toString());
        });
    }

    /**
     * 删除用户购物车中指定的商品
     */
    @Override
    public void deleteCartChecked(Long userId,Integer productId,String productValues) {
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, userId);
            redisUtil.hdel(redisKey, productId+":"+productValues);
    }

    @Override
    public void deleteAllUsersCart() {
        List<User> users = userMapper.selectList(null);
        users.forEach(user -> {
            selectAllCart(user.getId());
            deleteCartChecked(user.getId());
        });
    }
}
